package futbol.tacticas.concursantes.TacticaRouces;

import futbol.tacticas.*;
import futbol.tacticas.concursantes.Tactica;
import java.awt.Color;
import java.awt.Point;
import java.util.Vector;
import java.io.*;


/**
 *
 * @author Jacobo Rouces
 */
public class TacticaRouces implements Tactica{
            
    // Variables de uso frecuente
    SituacionJugadores sj;
    Vector <Comando> com;
    Point bola;
    Point bolaAntes = new Point(0,0);
    
    // Variables de estado de partida
    long marcador,marcaMiCampo,marcaSuCampo;
    long subMarcador=1;
    int golesMios,golesSuyos;
    long contadorBolaParada;
    
    // Variables de control de estrategia
    
    // Variables de medida del entorno no controlado
    double[] velocidadContrarios = new double[11];
    PuntoR[] posicionContrariosActual = new PuntoR[11];
    PuntoR[] posicionContrariosAnterior = new PuntoR[11];
    int longitudPrevisionBola=50;

    // Variables de cubridores
    int[] asignaciones = new int[11];
    int inicioC=1; //inclusive
    int finC = 10; //exclusive
    int lejano1,lejano2;
    int xInic=160;
    

    // Variables y métodos para el framework
    private int nValores[][]={
        {-155,   0,4},
        {xInic, 100,4},
        {xInic,  60,4},
        {150,  30,4},        
        {xInic,  10,4},
        {xInic, -10,4},
        {xInic, -30,4},
        {xInic, -60,4},
        {xInic,-100,4},
        {xInic,   0,4},
        {  70,   0,7} 
    };

    public String getNombre(){
        return "Anycast";
    }
    
    public Color getColor1(){
        return Color.black;
    }
    
    public Color getColor2(){
        return Color.black;
    }
    
    public Color getColorNumero(){
        return Color.red;
        //return new Color(0,215,0);
    }
    
    public int getFuerza(int n){
        return nValores[n][2];
    }
    public int getXInicial(int n){
        return nValores[n][0];
    }
    
    public int getYInicial(int n){
        return nValores[n][1];
    }
    

    public Vector<Comando> getComandos(SituacionJugadores sj){

        // DECLARACIÓN VARIABLES FRECUENTES
        this.sj=sj;
        bola=sj.getBola();
        com=new Vector();
        
        
        //$$$$$$$$$$$$$$$$$$$$$$4    INICIO FURÓN 
        PuntoR lugarDeIdaFuron = dameMovimientoSuperOptimizado(10,0,null);
        if ((!alguienLlegaAntesOptimista(lugarDeIdaFuron,null))&&(sj.getMisJugadores()[10].getX()>0)) {
            com.add(new ComandoIrA(10,(int)lugarDeIdaFuron.dameX(),(int)lugarDeIdaFuron.dameY()));
            //System.out.println(marcador);
        } else {
            com.add(new ComandoIrA(10, nValores[10][0]+Math.abs(bola.getY()/12), nValores[10][1]+bola.getY()/3));
        }
        com.add(new ComandoTiroAPuerta(10,0));
        //$$$$$$$$$$$$$$$$$$$$$$4    FIN FURÓN 
        
        /*
        // DEPURACIÓN VELOCIDAD BOLA
        System.out.println("Velocidad bola "+dameVelocidadBola().dameX()+"  "+dameVelocidadBola().dameY());
        PuntoR[] fut = damePosicionFuturaBola(dameVelocidadBola());
        for (int i=0;i<fut.length;i++){
            System.out.println(fut[i].dameX()+"  "+fut[i].dameY());
        }
        System.out.println(" ");
        System.out.println(" ");
        try {System.in.read();}catch(Exception e){;};
        */
        
        
                    
        //$$$$$$$$$$$$$$$$$$$$$$4    INICIO PORTERO 
        muevePorteroSinAlarma();
        gestionaPorteroSiAlarma();
        despejaPortero();
        //$$$$$$$$$$$$$$$$$$$$$$4    FIN PORTERO 
        
        
        
        
        
        //$$$$$$$$$$$$$$$$$$$$$$4    INICIO CUBRIDORES 
        asignaCubribles();
        gestionaCubridores();
        //$$$$$$$$$$$$$$$$$$$$$$4    FIN CUBRIDORES
        
        
        
        
        
        

        //ACTUALIZA VARIABLES DE ESTADO DE PARTIDA
        if (bola.getX()<0) marcaMiCampo++; else marcaSuCampo++;
        //System.out.println("Dominio: "+marcaMiCampo+"  "+marcaSuCampo);
        if ((bola.getX()>=160)&&(Math.abs(bola.getY())<30)) {golesMios++; subMarcador=0;}
        if  ((bola.getX()<=-160)&&(Math.abs(bola.getY())<30)) {golesSuyos++; subMarcador=0;}
        //System.out.println("Mios, tuyos : "+golesMios+"  "+golesSuyos);
        
        //¿BOLA PARADA? GESTIONA
        if ( (bola.getX()==bolaAntes.getX()) && (bola.getY()==bolaAntes.getY()) ) 
        { contadorBolaParada++; }
        else { contadorBolaParada=0; }
        //System.out.println("bola parada: "+contadorBolaParada);
        if (contadorBolaParada>50){
            //System.out.println("Estado estanco");
            if ( (golesSuyos>golesMios) || 
                 ((golesSuyos==golesMios)&&(bola.getX()<=0)&&(1800-marcador>=marcaSuCampo-marcaMiCampo)) || 
                 ((golesSuyos==golesMios)&&(bola.getX()>0)&&(1800-marcador<=marcaMiCampo-marcaSuCampo)) ) 
                com.add(new ComandoIrA(10,bola.getX(),bola.getY()));
        }
        
        
        
        //Medimos velocidades de los contrarios
        mideVelocidadesContrarios();
        
        
        //DEPURACION MEDICION VELOCIDAD CONTRARIOS
        //if (marcador%10==0)
        //System.out.println(marcador);
        /*
        if (marcador%10==0){
        for (int i=0; i<11; i++){
            System.out.print(velocidadContrarios[i]+"  ");
            }
        }
        */
        
        marcador++;
        subMarcador++;
        bolaAntes=bola;
        //try{ Thread.sleep(10); } catch(Exception e) {};
        return com;
    }
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    //@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
    //@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@   métodos    @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
    //@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
    
    
    
    
    
    private double norma(double x,double y){
        return Math.sqrt(Math.pow(x,2)+Math.pow(y,2));   
    }
    
    
    private PuntoR dameProyeccion(double p1x, double p1y, double p2x, double p2y, double vx, double vy){
        double r;
        if ((vx==0)&&(vy==0)) r=0;
        else r = -(p1x*vx-p2x*vx+p1y*vy-p2y*vy)/(Math.pow(vx,2)+Math.pow(vy,2));
        return new PuntoR( p1x+r*vx , p1y+r*vy );
    }
    
    
    
    
    
    
    
    
    //DEPREC
    private double dameDistContrMasCercano(double x,double y){
        int n= sj.getContrarioMasCerca(x,y);
        return norma(x-sj.getContrario()[n].getX(),y-sj.getContrario()[n].getY());
    }
    
    
    //DEPREC
    private int dameAmigoMasCercano(int n){
     int pivote = 0;
     double pivote2 = 1000;
       Point[] misJugadores=sj.getMisJugadores() ;
       for (int i=1;(i<11);i++){
           //System.out.println("para jugador "+i+" la distancia es "+norma ( misJugadores[i].getX()-misJugadores[n].getX() , misJugadores[i].getY()-misJugadores[n].getY() ));
       if ((i!=n)&&(pivote2 > norma ( misJugadores[i].getX()-misJugadores[n].getX() , misJugadores[i].getY()-misJugadores[n].getY() ))){
                    pivote2 = norma ( misJugadores[i].getX()-misJugadores[n].getX() , misJugadores[i].getY()-misJugadores[n].getY() ); pivote=i;}
       }
               //System.out.println(" el mas cercano a "+n+" es "+pivote);
        return pivote;

    }
    
    
    // A ELIMINAR
    private int dameAmigoMasCercaPorteriaContraria(){
     int indiceDistanciaMasCorta = 0;
     double distanciaMasCorta = 10000;
       Point[] misJugadores=sj.getMisJugadores() ;
       for (int i=1;i<11;i++){
           double dist = norma ( 160-misJugadores[i].getX() , -misJugadores[i].getY() );
           if (dist<distanciaMasCorta) {
               distanciaMasCorta=dist;
               indiceDistanciaMasCorta=i;
           }
       }
        return indiceDistanciaMasCorta;
    }
    

    
    private void jugadorMueveOptimizando(int nJug){
        
    double p2x = sj.getMisJugadores()[nJug].getX();
    double p2y = sj.getMisJugadores()[nJug].getY();
    double p1x = bola.getX();
    double p1y = bola.getY();
    double vx = dameVelocidadBola().dameX();
    double vy = dameVelocidadBola().dameY();
    PuntoR pr = dameProyeccion(p1x,p1y,p2x,p2y,vx,vy);
    double x = pr.dameX();//dameProyeccionX(p1x,p1y,p2x,p2y,vx,vy);
    double y = pr.dameY();//dameProyeccionY(p1x,p1y,p2x,p2y,vx,vy);
    //llegará?
    double v = norma(dameVelocidadBola());
    double r = (v+1)*v/2;
    double t = norma(x-p1x,y-p1y);
    if (r<t) com.add(new ComandoIrA( nJug , (int)p1x+vx*(r-1)/v , (int)p1y+vy*(r-1)/v )); 
    else com.add(new ComandoIrA(nJug,(int)x,(int)y));    
    }
    
    
    // flag=0:miequipo,=60:equipocontrario,=rest:coordenada y porteria-30
    private PuntoR dameMovimientoSuperOptimizado(int nJug, int flag, PuntoR velocidad){
        if (velocidad==null) velocidad=dameVelocidadBola();
        PuntoR[] futurasPosiciones = damePosicionFuturaBola(velocidad);
        PuntoR posicionJugadorN;
        int velocidadJugadorN;
        if (flag==0) {
            posicionJugadorN = new PuntoR (sj.getMisJugadores()[nJug].getX(),sj.getMisJugadores()[nJug].getY());
            velocidadJugadorN=10-nValores[nJug][2];
        } else if (flag==60) { 
            posicionJugadorN = new PuntoR (sj.getContrario()[nJug].getX(),sj.getContrario()[nJug].getY()); 
            velocidadJugadorN = (int)velocidadContrarios[nJug];
        } else {
            //modelización del punto de gol como jugador inmóvil.
            posicionJugadorN = new PuntoR (160,flag-30); 
            velocidadJugadorN = 0;
        }
        
        double distanciaRecorrer=10;
        double distanciaRecorrible=0;
        int futuraVelocidad=(int)(norma(velocidad)+1.5);
        int i=1;
        while ( ((distanciaRecorrible<distanciaRecorrer)||(futuraVelocidad>15))&&(i<futurasPosiciones.length) ) {
            distanciaRecorrer=norma(suma(futurasPosiciones[i],posicionJugadorN.negativo()));
            //System.out.println(distanciaRecorrer);
            distanciaRecorrible=velocidadJugadorN*i+10;
            //futuraVelocidad = norma(suma(futurasPosiciones[i],futurasPosiciones[i].negativo()));
            futuraVelocidad--;
            i++;
        }
        //System.out.println("  ");
        //System.out.println(futurasPosiciones[i-1].dameX()+"  "+futurasPosiciones[i-1].dameY());
        /*
        if (miEquipo==true) {
            com.add(new ComandoIrA(nJug,(int)futurasPosiciones[i-1].dameX(),(int)futurasPosiciones[i-1].dameY()));
        }
        return i;
        */
        futurasPosiciones[i-1].ponT(i);
        return futurasPosiciones[i-1];
    }
    

    
    private boolean alguienLlegaAntes(PuntoR lugarDeIda, PuntoR velocidad){
        int tiempoAlcanzarBola = lugarDeIda.dameT();
        if (tiempoAlcanzarBola==longitudPrevisionBola) return true;
        for (int i=0;i<11;i++){
            if (dameMovimientoSuperOptimizado(i,60,velocidad).dameT()<tiempoAlcanzarBola) return true;
        }
        return false;
    }
    
    
    private boolean alguienLlegaAntesOptimista(PuntoR lugarDeIda, PuntoR velocidad){
        int tiempoAlcanzarBola = lugarDeIda.dameT()-3;
        if (tiempoAlcanzarBola==longitudPrevisionBola) return true;
        for (int i=0;i<11;i++){
            if (dameMovimientoSuperOptimizado(i,60,velocidad).dameT()<tiempoAlcanzarBola) return true;
        }
        return false;
    }
    
    
    
    
    
    
    
    
    
    
    
    public void mideVelocidadesContrarios(){
        if (marcador==0) {
            for (int i=0;i<11;i++){velocidadContrarios[i]=3;
            posicionContrariosActual[i]=new PuntoR(sj.getContrario()[i].getX(),sj.getContrario()[i].getY());
            } //inicio al mínimo
        } else
        
            
        for (int i=0;i<11;i++){
            posicionContrariosAnterior[i]=posicionContrariosActual[i];
            posicionContrariosActual[i]=new PuntoR(sj.getContrario()[i].getX(),sj.getContrario()[i].getY());
            double velocidad = Math.floor ( norma ( 
                    posicionContrariosActual[i].dameX()-posicionContrariosAnterior[i].dameX() , 
                    posicionContrariosActual[i].dameY()-posicionContrariosAnterior[i].dameY() ) -0.5 );
            if ((velocidadContrarios[i]<velocidad)&&(subMarcador!=1)) velocidadContrarios[i]=velocidad;
            if (velocidadContrarios[i]>6) velocidadContrarios[i]=6;
            
        }
    
    }
    
    
    
    private PuntoR dameVelocidadBola(){
        PuntoR velocidadBola=new PuntoR( bola.getX()-bolaAntes.getX() , bola.getY()-bolaAntes.getY() );
        if (norma(velocidadBola)<22)
        return velocidadBola;
        else return new PuntoR(0,0);
    }
    
    
    
    private PuntoR[] damePosicionFuturaBola(PuntoR velocidad){
        
        PuntoR[] posicionesFuturas=new PuntoR[longitudPrevisionBola];
        posicionesFuturas[0]=new PuntoR(bola);
        PuntoR velocidadIterada= new PuntoR(velocidad.dameX(),velocidad.dameY());
        PuntoR restaVelocidad= new PuntoR(0,0);
        double normaVelocidad = norma(velocidad);
        if (normaVelocidad>0.001) restaVelocidad=velocidad.multiplicar(-1/normaVelocidad);
        
        for (int i=1;i<longitudPrevisionBola;i++){
            if (Math.abs(norma(velocidadIterada))>0.01) velocidadIterada=suma(velocidadIterada,restaVelocidad);
            posicionesFuturas[i]=suma(posicionesFuturas[i-1],velocidadIterada);
            
            //si la velocidad ya ha llegado a cero, que no siga disminuyendo
            if (Math.abs(norma(velocidadIterada))<1) velocidadIterada=new PuntoR(0,0);
            
            //control de rebote
            double x = posicionesFuturas[i].dameX();
            double y = posicionesFuturas[i].dameY();
            if (y>120) {
                posicionesFuturas[i].ponY(240-y);
                velocidadIterada=new PuntoR(velocidadIterada.dameX(),-velocidadIterada.dameY());
                restaVelocidad=new PuntoR(restaVelocidad.dameX(),-restaVelocidad.dameY());
            } else if (y<-120) {
                posicionesFuturas[i].ponY(-240-y);
                velocidadIterada=new PuntoR(velocidadIterada.dameX(),-velocidadIterada.dameY());
                restaVelocidad=new PuntoR(restaVelocidad.dameX(),-restaVelocidad.dameY());
            }
            if ((x>160)&&(Math.abs(y)>30)) {
                posicionesFuturas[i].ponX(320-x);
                velocidadIterada=new PuntoR(-velocidadIterada.dameX(),velocidadIterada.dameY());
                restaVelocidad=new PuntoR(-restaVelocidad.dameX(),restaVelocidad.dameY());
            } else if ((x<-160)&&(Math.abs(y)>30)) {
                posicionesFuturas[i].ponX(-320-x);
                velocidadIterada=new PuntoR(-velocidadIterada.dameX(),velocidadIterada.dameY());
                restaVelocidad=new PuntoR(-restaVelocidad.dameX(),restaVelocidad.dameY());
            }
            
        }
        
        return posicionesFuturas;
    }
    
    
    
    

    
    

    
    
    
    
    
    private void asignaCubribles(){

        Point[] contrarios = sj.getContrario();
        Point[] propios = sj.getMisJugadores();
        
        if (subMarcador==1){
            
            //System.out.println("cucu");
            
            for (int i=0;i<11;i++) asignaciones[i]=i;
            
            double pivote;
            int[] contrariosAsignados = new int[11];
            int pivoteP=0;
            int pivoteP2=0;
            int[] propiosAsignados = new int [11];
            double dist,dist2;

            for (int i=0;i<finC-inicioC;i++){  //de entre todos los contrarios
                pivote=500;
                for (int k=0;k<11;k++){  //buscamos el (i+1)ésimo más lejano resp portería, finC-inicioC veces, que será el número pivoteP
                    dist2=norma(contrarios[k].getX()+160,contrarios[k].getY());
                    if ((dist2<pivote)&&( contrariosAsignados[k]!=1 )) { pivote=dist2; pivoteP=k; }
                }
                contrariosAsignados[pivoteP]=1;
                
                    dist=500;
                    for (int j=inicioC; j<finC;j++){ //para él buscamos el propio más cercano que no esté asignado
                        if  ((norma(contrarios[pivoteP].getX()-propios[j].getX(),contrarios[pivoteP].getY()-propios[j].getY())<dist) && ( propiosAsignados[j]!=1 )){
                                dist=norma(contrarios[pivoteP].getX()-propios[j].getX(),contrarios[pivoteP].getY()-propios[j].getY()); 
                                pivoteP2=j; 
                        }
                    }
                asignaciones[pivoteP2]=pivoteP;
                propiosAsignados[pivoteP2]=1;          
            }
        
            for(int f=0; f<11; f++) if (contrariosAsignados[f]==0) lejano1=f;
            for(int f=0; f<11; f++) if ((contrariosAsignados[f]==0)&&(f!=lejano1)) lejano2=f;
            
        } else {
            
            
            double pivote;
            int[] contrariosAsignados= new int[11];
            int pivoteP=0;
            double dist;
            
            for (int i=0; i<10; i++){ //vuelve a ordenar de cercano a lejano
                
                pivote=500;
                for (int j=0; j<11; j++){
                    dist=norma(contrarios[j].getX()+160,contrarios[j].getY());
                    if ((dist<pivote)&&(contrariosAsignados[j]!=1)) {pivoteP=j; pivote=dist;}
                }
                contrariosAsignados[pivoteP]=1;
                
                if ( (i<9) && ((pivoteP==lejano1)||(pivoteP==lejano2)) ) {subMarcador=0; //System.out.println("reseteado");
                                                                         }
                  
            } 
            
        }

        return;
    }
    
    
    
    
    private void cubre(int nJug, int nCon){
        
        //posicionamiento
        double x = bola.getX() - sj.getContrario()[nCon].getX();
        double y = bola.getY() - sj.getContrario()[nCon].getY();
        double n = norma(x,y)+0.001;
        double nx = sj.getContrario()[nCon].getX()+(x/n)*20;
        double ny = sj.getContrario()[nCon].getY()+(y/n)*20;
        com.add(new ComandoIrA(nJug,(int)nx,(int)ny));

        
        // condición especial, a poner antes
        PuntoR lugarDeIdaOptimo = dameMovimientoSuperOptimizado(nJug,0,null);
        if ((!alguienLlegaAntes(lugarDeIdaOptimo,null))&&(lugarDeIdaOptimo.dameT()<5)) {
            com.add(new ComandoIrA(nJug,(int)lugarDeIdaOptimo.dameX(),(int)lugarDeIdaOptimo.dameY()));
        }
        
        
        //disparo perp
        if (norma(  bola.getX()-sj.getMisJugadores()[nJug].getX()  ,  bola.getY()-sj.getMisJugadores()[nJug].getY())<15 ){
            
            double lx,ly;//coordenadas punto objetivo
            int nAt = dameAmigoMasCercaPorteriaContraria();
            lx = sj.getMisJugadores()[nAt].getX()-bola.getX();
            ly = sj.getMisJugadores()[nAt].getY()-bola.getY();

            if ((lx*x+ly*y)<0) //producto escalar negativo
                if ((lx*y-ly*x)>0) //producto vectorial positivo, primer factor lx,ly
                    {lx=y;
                     ly=-x;}
                else{lx=-y;
                     ly=x;}
            com.add(new ComandoGolpearBola( nJug , bola.getX()+lx*100 , bola.getY()+ly*100 ));
            
            

            
            
        }

        
    }
    
    
    
    public void dispara(int nJug){
        
        if (norma(  bola.getX()-sj.getMisJugadores()[nJug].getX()  ,  bola.getY()-sj.getMisJugadores()[nJug].getY())<12 ){
            
            
            // analiza pase a furon y calcula preliminares de pase general
            int numeroDireccionesAnalizar = 400;
            double vIni = getFuerza(nJug)*3;
            boolean[] destinosImposiblesPasarFuron = new boolean[numeroDireccionesAnalizar];
            boolean[] destinosImposiblesPasarGeneral = new boolean[numeroDireccionesAnalizar];
            int[] miosPrimero = new int[numeroDireccionesAnalizar];
            double ang=0;
            PuntoR velocidadAnalizada;
            //int[] direccionesSopesarPaseGeneral = new int[numeroDireccionesAnalizar];
            //orden agujas de reloj, empezando a las 12
            for (int i=0;i<numeroDireccionesAnalizar;i++) {
                ang = i*4*Math.PI/numeroDireccionesAnalizar;
                velocidadAnalizada=new PuntoR(Math.sin(ang)*vIni,-Math.cos(ang)*vIni);
                destinosImposiblesPasarFuron[i]=alguienLlegaAntes(dameMovimientoSuperOptimizado(10,0,velocidadAnalizada),velocidadAnalizada);
                  /*
                  int elMioPrimero = dameCualLlegaPrimero(0,velocidadAnalizada,100);
                  destinosImposiblesPasarGeneral[i]=alguienLlegaAntes(dameMovimientoSuperOptimizado(elMioPrimero,0,velocidadAnalizada),velocidadAnalizada);
                  miosPrimero[i]=elMioPrimero;
                  */ 
                  int elContrarioPrimero = dameCualLlegaPrimero(60,velocidadAnalizada,100);
                  destinosImposiblesPasarGeneral[i]=(dameMovimientoSuperOptimizado(elContrarioPrimero,60,velocidadAnalizada).dameT()<6);
                  //direccionesSopesarPaseGeneral[i]=dameMovimientoSuperOptimizado(elContrarioPrimero,60,velocidadAnalizada).dameT();
                  miosPrimero[i]=elContrarioPrimero;
            }
            
            
            Point lateralesHuecoPaseFuron = dameCentroArray(destinosImposiblesPasarFuron);
            double pesoDelDisparoAFuron = (lateralesHuecoPaseFuron.getY()-lateralesHuecoPaseFuron.getX())*5; //porcentaje de la doble vuelta
            //apertura aleatoria = numposanaliz/20=20 (400) 20*5=100
            if (pesoDelDisparoAFuron>100) pesoDelDisparoAFuron=100; 
            //condiciones extra para evitar el tiro a furon
            if (sj.getMisJugadores()[10].getX()<0) pesoDelDisparoAFuron=0;
            if (sj.getMisJugadores()[nJug].getX()<-50) pesoDelDisparoAFuron=0;
            
            
            //analiza tiro a portería
            Point intentoAPorteria = buscaHuecoPorteria(nJug);
            int coordenadaAPorteria = (int)intentoAPorteria.getX();
            int pesoDelDisparoAPorteria = (int)intentoAPorteria.getY();
            //condiciones extra para evitar el tiro a porteria
            if (sj.getMisJugadores()[nJug].getX()<-50) pesoDelDisparoAPorteria=0;

            
            
            if (((pesoDelDisparoAFuron!=0)||(pesoDelDisparoAPorteria)!=0)) {
                /*
                double fde = ((lateralesHueco.getX()+lateralesHueco.getY())/2)*4*Math.PI/numeroDireccionesAnalizar;
                System.out.println("pesoDelDisparoAFuron: "+pesoDelDisparoAFuron+"  direccion: "+fde);
                System.out.println("pesoDelDisparoAPorteria: "+pesoDelDisparoAPorteria);
                try {System.in.read();}catch(Exception e){;};
                */
                
                if (pesoDelDisparoAFuron<pesoDelDisparoAPorteria){

                    double vectX = bola.getX()+(160-bola.getX())*20;
                    double vectY = bola.getY()+(coordenadaAPorteria-30-bola.getY())*20;
                    com.add(new ComandoGolpearBola( nJug , vectX , vectY ));
                    //System.out.println("tiro a puerta del "+nJug+" a la coordenada "+coordenadaAPorteria+" , referencia punto "+vectX+" "+vectY);
                    
                } else {
                
                    double angulo = ((lateralesHuecoPaseFuron.getX()+lateralesHuecoPaseFuron.getY())/2)*4*Math.PI/numeroDireccionesAnalizar;
                    double vectX = bola.getX()+Math.sin(angulo)*100;
                    double vectY = bola.getY()-Math.cos(angulo)*100;
                    com.add(new ComandoGolpearBola( nJug , vectX , vectY ));
                    
                    
                    
                    
                }
                
                

            } else { //si ni se puede a furon ni a porteria, pase general
                //try {System.in.read();}catch(Exception e){;};
                
                int[] direccionesSopesarPaseGeneral = new int[numeroDireccionesAnalizar];
                PuntoR restaBola = new PuntoR (bola);
                restaBola = restaBola.multiplicar(-1);
                PuntoR objetivo = new PuntoR(110,sj.getMisJugadores()[10].getY());
                PuntoR vectorDiferencial = suma ( objetivo , restaBola );
                double distanciaAlObjetivo = norma (vectorDiferencial);
                //angulo objetivo medido en referencia clásica
                //equivalente a desfase
                double anguloObjetivo = Math.acos ( vectorDiferencial.dameX()/distanciaAlObjetivo );
                if (vectorDiferencial.dameY()>0) { anguloObjetivo=2*Math.PI-anguloObjetivo; }
                //System.out.println("DESFASE:  "+anguloObjetivo);
                for (int i=0;i<numeroDireccionesAnalizar;i++){
                    if (destinosImposiblesPasarGeneral[i]) {
                        direccionesSopesarPaseGeneral[i]=0;
                    } else {
                        direccionesSopesarPaseGeneral[i]=1000;
                    }
                    int bonificacion = (int)(20*Math.sin(i*Math.PI/100+anguloObjetivo));
                    direccionesSopesarPaseGeneral[i]+=bonificacion;
                }
                
                double direccionElegida = dameMaximoArrayPasoBajo(direccionesSopesarPaseGeneral);
                /*
                //depura bug laterales 1/1
                System.out.println("ini");
                for (int i=0;i<400;i++) {
                    System.out.println(i+"  "+miosPrimero[i]+"   "+direccionesSopesarPaseGeneral[i]);
                }
                //try {System.in.read();}catch(Exception e){;};
                System.out.println("fin");
                System.out.println("direccion pase general del "+nJug+" jugador: "+direccionElegida);
                try {System.in.read();}catch(Exception e){;};
                */
                double angulo = (direccionElegida)*4*Math.PI/numeroDireccionesAnalizar;
                double vectX = bola.getX()+Math.sin(angulo)*100;
                double vectY = bola.getY()-Math.cos(angulo)*100;
                com.add(new ComandoGolpearBola( nJug , vectX , vectY ));

                
            
            
            }
            
        }
        
    }
    
    
    
    private void gestionaCubridores(){  
        for (int i=inicioC;i<finC;i++){
            cubre(i,asignaciones[i]);   
            dispara(i);
        }
        return;
    }
    
    
    
    //como X devuelve la coordenada vertical de portería libre, 1-59. 0 si no hay posibilidades.
    //como Y devuelve el porcentaje de peso para la accion
    private Point buscaHuecoPorteria(int nJug){
        
       double vIni = getFuerza(nJug)*3;
       boolean[] destinosImposibles = new boolean[60];
       boolean hayAlgo=false;
       for (int i=1;i<60;i++) {
           //PuntoR destino = new PuntoR( 160 , i-30 );
           PuntoR disparo = new PuntoR( 160-bola.getX() , i-30-bola.getY() );
           double norma=norma(disparo)+0.001;
           PuntoR velocidad=disparo.multiplicar(vIni/norma);
           destinosImposibles[i]=alguienLlegaAntes(dameMovimientoSuperOptimizado(0,i,velocidad),velocidad);
           if (!destinosImposibles[i]) hayAlgo=true;
       }
       
       Point lateralesHueco = dameCentroArray(destinosImposibles);
       
       int indiceElegido = (int)((lateralesHueco.getX()+lateralesHueco.getY())/2);
       
       //calculo del angulo de posibilidades, y por tanto del peso del disparo
       PuntoR v1 = new PuntoR ( 160-bola.getX() , lateralesHueco.getX()-30-bola.getY() );
       PuntoR v2 = new PuntoR ( 160-bola.getX() , lateralesHueco.getY()-30-bola.getY() );
       double productoEscalar = v1.dameX()*v2.dameX()+v1.dameY()*v2.dameY();
       double coseno = productoEscalar/(norma(v1)*norma(v2));
       double angulo = Math.acos(coseno);
       angulo=angulo*500/Math.PI;
       if (angulo>100) angulo=100;  
       /*
       if (indiceElegido!=0) {
           System.out.println(angulo+" arriba:"+lateralesHueco.getX()+"  centro:"+indiceElegido+"  abajo:"+lateralesHueco.getY()+"  ");
           try {System.in.read();}catch(Exception e){;};
       }
       */
       return new Point ( indiceElegido , (int)angulo );
       
        
    }
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    private void despejaPortero(){
        
        if (norma(  bola.getX()-sj.getMisJugadores()[0].getX()  ,  bola.getY()-sj.getMisJugadores()[0].getY())<15 ){
            
            int numeroDireccionesAnalizarPortero = 100;
            //PuntoR[] direccionesAnalizar = new PuntoR[numeroDireccionesAnalizar];
            double vIni = getFuerza(0)*3;
            int[] direccionesAnalizar = new int[numeroDireccionesAnalizarPortero];
            double ang=0;
            PuntoR velocidadAnalizada;
            for (int i=0;i<numeroDireccionesAnalizarPortero;i++) {
                ang = i*Math.PI/numeroDireccionesAnalizarPortero;
                velocidadAnalizada=new PuntoR(Math.sin(ang)*vIni,-Math.cos(ang)*vIni);
                int elMasPeligroso=dameCualLlegaPrimero(60,velocidadAnalizada,100);
                PuntoR puntoContactoPeligro = dameMovimientoSuperOptimizado(elMasPeligroso,60,velocidadAnalizada);
                direccionesAnalizar[i]=puntoContactoPeligro.dameT();
                //System.out.println("angulo "+i+" , el suyo mas cercano es "+elMasPeligroso+" a instantes "+direccionesAnalizar[i]);

            }

            int indiceElegido = dameMaximoArrayPasoBajo(direccionesAnalizar);
            /*
            System.out.println("indice elegido al final: "+indiceElegido);
            double v = norma(dameVelocidadBola()); 
            System.out.println("-90 grados de tiro para el portero. velocidad de la bola: "+v);
            try {System.in.read();}catch(Exception e){;};
            */
            ang = indiceElegido*Math.PI/numeroDireccionesAnalizarPortero;
            double x = bola.getX()+Math.sin(ang)*100;
            double y = bola.getY()-Math.cos(ang)*100;
            
            com.add(new ComandoGolpearBola(0,x,y));
            
        }
        
    }
    
    
    //deprec
    private  boolean chequeaAlarmaPortero(){
        
        double choque = bola.getY()+dameVelocidadBola().dameY()*
                ((-160-bola.getX())/dameVelocidadBola().dameX() );
        boolean a = ((Math.abs( choque ) < 36)&&(dameVelocidadBola().dameX()<0));
        
        double d = norma ((bola.getX()+160)/(1.5),bola.getY());
        double v = norma (dameVelocidadBola());
        //double v = norma (dameVelocidadBolaX(sj),dameVelocidadBolaY(sj));
        //double r = (v+1)*v/2;
        //boolean b = r+40 > d;
        boolean b = d<70;
        //if (a==true) System.out.println("direccion peligrosa"); else System.out.println("safe");
        
        /*
        if(a&&b){
            try{
        char caracter = (char) System.in.read(); 
            }catch(Exception e){}   
        }
        */
        
        return (a && b);
    }
    
    
    
    private void gestionaPorteroSiAlarma(){
        
        PuntoR lugarDeIdaPortero = dameMovimientoSuperOptimizado(0,0,null);
        
        int tiempoAlcanzarBola = lugarDeIdaPortero.dameT();
        boolean debeIr=true;
        double distanciaAPuerta;
        distanciaAPuerta = norma( lugarDeIdaPortero.dameX()+160 , lugarDeIdaPortero.dameY() );
        if (distanciaAPuerta>67) debeIr=false;
        //System.out.println(debeIr);
        PuntoR dondeLeDariaElJugI;
        for (int i=0;i<11;i++){
            dondeLeDariaElJugI=dameMovimientoSuperOptimizado(i,60,dameVelocidadBola());
            if (dondeLeDariaElJugI.dameT()<tiempoAlcanzarBola){
                debeIr=false;
            }
        }
        //si nadie le da antes y la distancia es menor que 67
        if (debeIr) {
            double x = lugarDeIdaPortero.dameX();
            double y = lugarDeIdaPortero.dameY();
            if (x<-150) {
                x=-150;
                /*
                System.out.println("me pasaba");
                try {System.in.read();}catch(Exception e){;};
                */
            }
            com.add(new ComandoIrA(0,(int)x,(int)y));
        }

    }
    
    
    
    private void muevePorteroSinAlarma(){
        double signo = bola.getY()/Math.abs(bola.getY());
        if (bola.getY()==0) signo=1;
        PuntoR pr = dameProyeccion( bola.getX() , bola.getY() , -155 , 30*signo , -160-bola.getX() , -bola.getY() );
        PuntoR proyeccion = dameProyeccion( bola.getX() , bola.getY() , -155 , 30*signo , -160-bola.getX() , -bola.getY() );
        double x=proyeccion.dameX();
        double y=proyeccion.dameY(); 
        /*
        double x = -155;
        double y = bola.getY();
        if (y>30) y=30;
        if (y<-30) y=-30;
         * */
        com.add(new ComandoIrA(0,(int)x,(int)y));
    }
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    //equipo mio=0; equiposuyo=60
    private int dameCualLlegaPrimero(int equipo, PuntoR velocidad,int excepcion){
        double minimo = 100000;
        int indiceMinimo = 0;
        double pivote = 0;
        for (int i=0;((i<11)&&(i!=excepcion));i++) {
            pivote = dameMovimientoSuperOptimizado(i,equipo,velocidad).dameT();
            if (pivote<minimo) {
                minimo = pivote;
                indiceMinimo = i;
            }
        }
        return indiceMinimo;
    }
    
    
    
    
    private Point dameCentroArray(boolean[] destinosImposibles){
        
       //buscamos hueco más ancho
       int contador=0;
       int maxContador=0;
       int indiceMaxContador=0;
       for (int i=1;i<destinosImposibles.length;i++){
           //System.out.println(destinosImposibles[i]);
           if (!destinosImposibles[i]) {
               contador++;
               if (maxContador<contador){
                   maxContador=contador;
                   indiceMaxContador=i;
               }
           } else {
               contador=0;
           }
       }
       /*
           System.out.println("borde porteria. velocidad de la bola es "+norma(dameVelocidadBola()));
           double devolucion = indiceMaxContador-maxContador/2;
           System.out.println("indice devuelto: "+devolucion);
           try {System.in.read();}catch(Exception e){;};
       */
       return new Point(indiceMaxContador-maxContador,indiceMaxContador);
       //return (int)(indiceMaxContador-maxContador/2);
    }
    
    
    
    
    private int dameMaximoArrayPasoBajo(int[] array){
        int tamanoVentana = 20; //pi quintos de mi amor
        int suma=0;
        for (int i=0;i<tamanoVentana;i++){
            suma=suma+array[i];
        }
        int sumaMaxima=suma;
        int indiceSumaMaxima=0;
        int corrimientos=array.length-tamanoVentana;
        for (int i=0;i<corrimientos;i++){
            suma=suma-array[i]+array[i+tamanoVentana];
            if (suma>sumaMaxima) {sumaMaxima=suma; indiceSumaMaxima=i;}
        }
        int indiceCentral = (int)(indiceSumaMaxima+tamanoVentana/2);
        return indiceCentral;
    }
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    //@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
    //@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@   clase punto    @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
    //@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
    
    
    
    
    public PuntoR suma(PuntoR p1, PuntoR p2){
        return new PuntoR(p1.dameX()+p2.dameX(),p1.dameY()+p2.dameY());
    }
        
    double norma(PuntoR punto){
        return norma(punto.dameX(),punto.dameY());
    }
    
    
    // Clase interna Punto de dos dimensiones con coordenadas Reales y factor entero temporal opcional 
   public class PuntoR{
        
        private double x=0;
        private double y=0;
        private int t=0;
        
        PuntoR(double x,double y){
        this.x=x;    
        this.y=y;
        }
        
        PuntoR(Point puntoI){
        x=puntoI.getX();    
        y=puntoI.getY();
        }
        
        PuntoR multiplicar(double f){
            return new PuntoR(x*f,y*f);
        }
        
        PuntoR negativo(){
            return new PuntoR(-x,-y);
        }
        
        
        double dameX(){
            return x;
        }
        double dameY(){
            return y;
        } 
        int dameT(){
            return t;
        } 
        void ponX(double x){
            this.x=x;
        }
        void ponY(double y){
            this.y=y;
        }
        void ponT(int t){
            this.t=t;
        }
    }
    
    
    
}
